package it.mauriziobasile.sincrodir.gui;

import it.mauriziobasile.sincrodir.eccezioni.DirNullEcc;
import it.mauriziobasile.sincrodir.eccezioni.VersoNonImpostatoEcc;
import it.mauriziobasile.sincrodir.entita.Directory;
import it.mauriziobasile.sincrodir.entita.File;
import it.mauriziobasile.sincrodir.entita.GestoreRisorse;
import it.mauriziobasile.sincrodir.logica.FileSystem;
import it.mauriziobasile.sincrodir.logica.Sincronizzatore;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

public class FinestraPrincipale extends JFrame {
    private static final long serialVersionUID = 6728853189058185671L;
    private ResourceBundle txtBundle;
    private Properties configProperties;
    private BoxLayout boxLayout;
    private Container questoContenitore;
    private JButton sfoglia1Pulsante;
    private JButton sfoglia2Pulsante;
    private JButton analizzaPulsante;
    private JButton vaiPulsante;
    private JButton itPulsante;
    private JButton enPulsante;
    private JPanel dir1Panel;
    private JPanel dir2Panel;
    private JPanel controlPanel;
    private JPanel diffPanel;
    private JSplitPane diffDirSplit;
    private DifferenzeTreeModel diff1Model;
    private DifferenzeTreeModel diff2Model;
    private JTextField dir1Text;
    private JTextField dir2Text;
    private JTree tree1;
    private JTree tree2;
    private Directory dir1;
    private Directory dir2;
    private Sincronizzatore sincro;
    private JLabel stato;
    private JRadioButton verso1;
    private JRadioButton verso2;
    private JRadioButton completo;
    private ButtonGroup verso;
    private Locale locale;
    
    public FinestraPrincipale() {
        questoContenitore = getContentPane();
        locale= Locale.getDefault();
        init();   
        abilitaSincGui(false);
        pack();
    }

    private void init() {
        txtBundle = GestoreRisorse.instanza().getRisorse(locale);
        configProperties = GestoreRisorse.instanza().getPropieta();
        questoContenitore.removeAll();
        sincro = new Sincronizzatore();
        setTitle(txtBundle.getString("finestraPrincipale.titolo"));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(Integer.parseInt(configProperties.getProperty("finestraPrincipale.width.min", "640")), Integer.parseInt(configProperties.getProperty("finestraPrincipale.height.min", "480"))));
        setPreferredSize(new Dimension(Integer.parseInt(configProperties.getProperty("finestraPrincipale.width", "640")), Integer.parseInt(configProperties.getProperty("finestraPrincipale.height", "480"))));
        diff1Model = new DifferenzeTreeModel(null);
        diff2Model = new DifferenzeTreeModel(null);
        boxLayout = new BoxLayout(questoContenitore, BoxLayout.Y_AXIS);
        questoContenitore.setLayout(boxLayout);
        dir1Panel = new JPanel(new FlowLayout());
        dir2Panel = new JPanel(new FlowLayout());
        controlPanel = new JPanel(new FlowLayout());
        diffPanel = new JPanel();
        // BoxLayout diffBoxLayout = new BoxLayout(diffPanel, BoxLayout.X_AXIS);
        stato = new JLabel();
        questoContenitore.add(dir1Panel);
        questoContenitore.add(dir2Panel);
        questoContenitore.add(controlPanel);
        questoContenitore.add(diffPanel);

        dir1Text = new JTextField();
        dir1Text.setPreferredSize(new Dimension(300, 25));
        sfoglia1Pulsante = new JButton(txtBundle.getString("finestraPrincipale.sfoglia1Button"));
        sfoglia1Pulsante.setSize(Integer.parseInt(configProperties.getProperty("finestraPrincipale.sfogliaPulsanti.width", "50")), Integer.parseInt(configProperties.getProperty("finestraPrincipale.sfogliaPulsanti.height", "20")));

        dir2Text = new JTextField();
        dir2Text.setPreferredSize(new Dimension(300, 25));
        sfoglia2Pulsante = new JButton(txtBundle.getString("finestraPrincipale.sfoglia2Button"));
        sfoglia2Pulsante.setSize(Integer.parseInt(configProperties.getProperty("finestraPrincipale.sfogliaPulsanti.width", "50")), Integer.parseInt(configProperties.getProperty("finestraPrincipale.sfogliaPulsanti.height", "20")));
        analizzaPulsante = new JButton(txtBundle.getString("finestraPrincipale.analizzaButton"));
        vaiPulsante = new JButton(txtBundle.getString("finestraPrincipale.vaiButton"));
        itPulsante = new JButton(txtBundle.getString("finestraPrincipale.lang.it"));
        enPulsante = new JButton(txtBundle.getString("finestraPrincipale.lang.en"));
        dir1Panel.add(dir1Text);
        dir1Panel.add(sfoglia1Pulsante);
        dir2Panel.add(dir2Text);
        dir2Panel.add(sfoglia2Pulsante);
        tree1 = new JTree(diff1Model);
        tree1.putClientProperty("JTree.lineStyle", "Angled");
        tree2 = new JTree(diff2Model);
        tree2.putClientProperty("JTree.lineStyle", "Angled");
        diffDirSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree1), new JScrollPane(tree2));
        BorderLayout bl = new BorderLayout();
        bl.setHgap(3);
        bl.setVgap(3);
        diffPanel.setLayout(bl);
        diffPanel.add(diffDirSplit, BorderLayout.CENTER);
        controlPanel.add(analizzaPulsante);
        controlPanel.add(vaiPulsante);
        controlPanel.add(itPulsante);
        controlPanel.add(enPulsante);
        verso = new ButtonGroup();
        verso1 = new JRadioButton("1->2", false);
        completo = new JRadioButton("1<->2", true);
        sincro.setVerso(Sincronizzatore.COMPLETO);
        verso2 = new JRadioButton("1<-2", false);
        verso1.setActionCommand(">");
        completo.setActionCommand("<>");
        verso2.setActionCommand("<");

        verso1.addActionListener(new VersoAscoltatoreAzione(this));
        completo.addActionListener(new VersoAscoltatoreAzione(this));
        verso2.addActionListener(new VersoAscoltatoreAzione(this));
        verso.add(verso1);
        verso.add(completo);
        verso.add(verso2);
        controlPanel.add(verso1);
        controlPanel.add(completo);
        controlPanel.add(verso2);
        diffPanel.add(controlPanel, BorderLayout.PAGE_START);
        diffPanel.add(stato, BorderLayout.PAGE_END);
        sfoglia1Pulsante.addActionListener(new SfogliaAscoltatoreAzione(this));
        sfoglia1Pulsante.setActionCommand("1");
        sfoglia2Pulsante.addActionListener(new SfogliaAscoltatoreAzione(this));
        sfoglia2Pulsante.setActionCommand("2");
        vaiPulsante.addActionListener(new VaiAscoltatoreAzione(this));
        vaiPulsante.setEnabled(false);
        analizzaPulsante.addActionListener(new AnalizzaAscoltatoreAzione(this));
        dir1Text.addKeyListener(new DirTestoAscoltatoreTasti(this));

        dir2Text.addKeyListener(new DirTestoAscoltatoreTasti(this));
        stato(txtBundle.getString("finestraPrincipale.benvenuto"));
        itPulsante.addActionListener(new ActionListener() {         
            @Override
            public void actionPerformed(ActionEvent e) {
                locale = new Locale("it","IT");
                init();
            }
        });
        
        enPulsante.addActionListener(new ActionListener() {         
            @Override
            public void actionPerformed(ActionEvent e) {
                locale = new Locale("en","US");
                init();
            }
        });

    }

    public void setDirText(String txt, int quale) {
        if (quale == 1)
            dir1Text.setText(txt);
        if (quale == 2)
            dir2Text.setText(txt);
    }

    public void stato(String mess) {
        this.stato.setText(mess);
        this.stato.setToolTipText(mess);
    }

    public boolean verificaDir() {
        return FileSystem.esisteDir(dir1Text.getText()) && FileSystem.esisteDir(dir2Text.getText());
    }

    public void costruisciAlberi() {
        dir1 = new Directory(dir1Text.getText(), true);
        diff1Model.setRoot(new DefaultMutableTreeNode(dir1.getName()));
        costruisciAlbero(dir1, diff1Model);
        expandAll(tree1, new TreePath(diff1Model.getRoot()), true);

        dir2 = new Directory(dir2Text.getText(), true);
        diff2Model.setRoot(new DefaultMutableTreeNode(dir2.getName()));
        costruisciAlbero(dir2, diff2Model);
        expandAll(tree2, new TreePath(diff2Model.getRoot()), true);
        sincro.setDir(dir1, 1);
        sincro.setDir(dir2, 2);
        vaiPulsante.setEnabled(true);
    }

    public void vai(){
        try {
            sincro.vai(true);
            if (sincro.getDifferenzeFile(2)==0 && sincro.getDifferenzeFile(1)==0)
            {
                JOptionPane.showMessageDialog(this, txtBundle.getString("finestraPrincipale.vai.dialogo.giasincronizzate"));  
            }
            else{
                Object[] options = {txtBundle.getString("finestraPrincipale.vai.dialogo.si"),txtBundle.getString("finestraPrincipale.vai.dialogo.no")};
                Object [] info = new Object[]{dir1.getName(),dir2.getName(),sincro.getDifferenzeFile(2),sincro.getDifferenzeFile(1)};
                String message = MessageFormat.format(txtBundle.getString("finestraPrincipale.vai.dialogo.messaggio"),info);
                int n = JOptionPane.showOptionDialog(this,message,txtBundle.getString("finestraPrincipale.vai.dialogo.titolo"),JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE,null,options,options[0]);
                if (n==JOptionPane.YES_OPTION){
                    stato(txtBundle.getString("finestraPrincipale.vai.stato"));
                    sincro.vai(false);
                    vaiPulsante.setEnabled(false);
                    stato(txtBundle.getString("finestraPrincipale.vai.fatto"));
                }
            }
        } catch (VersoNonImpostatoEcc e) {
            JOptionPane.showMessageDialog(this, txtBundle.getString("finestraPrincipale.vai.errore.versononimpostato"));
        } catch (DirNullEcc e) {
            JOptionPane.showMessageDialog(this, txtBundle.getString("finestraPrincipale.vai.errore.dinull"));
        }
    }
    
    public void abilitaSincGui(boolean abil) {
        analizzaPulsante.setEnabled(abil);
        verso1.setEnabled(abil);
        verso2.setEnabled(abil);
        completo.setEnabled(abil);
        
    }

    private void costruisciAlbero(Directory dir, DifferenzeTreeModel model) {
        model.setRoot(costruisciNodo(dir));
    }

    private DefaultMutableTreeNode costruisciNodo(Directory dir) {
        DefaultMutableTreeNode nodo = null;
        if (dir.isAlberizzato()) {
            nodo = new DefaultMutableTreeNode(dir.getName());
            nodo.setAllowsChildren(true);
            for (Directory directory : dir.getDirFigli()) {
                nodo.add(costruisciNodo(directory));
            }
            for (File file : dir.getFileFigli()) {
                nodo.add(new DefaultMutableTreeNode(file.getName()));
            }
        }
        return nodo;
    }

    private void expandAll(JTree tree, TreePath parent, boolean expand) {
        TreeNode node = (TreeNode) parent.getLastPathComponent();
        if (node.getChildCount() >= 0) {
            for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
                TreeNode n = (TreeNode) e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandAll(tree, path, expand);
            }
        }
        if (expand) {
            tree.expandPath(parent);
        } else {
            tree.collapsePath(parent);
        }
    }

    public void verso(int verso) {
        sincro.setVerso(verso);
        switch (verso) {
        case Sincronizzatore.DA1A2:
            stato(txtBundle.getString("finestraPrincipale.msg.verso.da1a2"));
            break;
        case Sincronizzatore.COMPLETO:
            stato(txtBundle.getString("finestraPrincipale.msg.verso.completo"));
            break;
        case Sincronizzatore.DA2A1:
            stato(txtBundle.getString("finestraPrincipale.msg.verso.da2a1"));
            break;
        default:
            break;
        }
    }
}
